package com.suning.sawp.service.impl.store;


import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.gson.reflect.TypeToken;
import com.mongodb.AggregationOutput;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
import com.suning.framework.dal.client.DalClient;
import com.suning.sawp.cache.RedisClient;
import com.suning.sawp.constants.CacheKeyConstants;
import com.suning.sawp.dto.region.RegionDto;
import com.suning.sawp.intf.model.BranchInfo;
import com.suning.sawp.intf.store.StoreInfoService;
import com.suning.sawp.po.store.StaffInfo;
import com.suning.sawp.po.store.StoreInfo;
import com.suning.sawp.po.store.StoreInfo.StoreAttributes;
import com.suning.sawp.remote.dto.StoreBaseInfo;
import com.suning.sawp.remote.intf.StoreInfoRemoteService;
import com.suning.sawp.service.util.DJStringUtils;
import com.suning.sawp.service.util.GsonUtils;
import com.suning.sawp.service.util.RedisCacheUtils;

/**
 * 
 * 门店数据<br> 
 * 〈功能详细描述〉
 *
 * @author 13071470
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Service
public class StoreInfoServiceImpl implements StoreInfoService, StoreInfoRemoteService{
    @Resource
    MongoTemplate mongoTemplate;
    
    @Autowired
    RedisCacheUtils   cacheUtils;
    
    @Autowired
    RedisClient   redisClient;
    
    @Resource
    DalClient dalClient;
    
    private static final Logger LOGGER = LoggerFactory.getLogger(StoreInfoServiceImpl.class);

    @Override
    public StoreInfo queryStoreByCode(String storeCode) {
        StoreInfo store = cacheUtils.hget(CacheKeyConstants.STORE_INFO, storeCode, StoreInfo.class);
        if(store == null){
            Query query = new Query();
            Criteria criteria = new Criteria();
            criteria.and(StoreAttributes.STORE_CODE).is(storeCode);
            query.addCriteria(criteria);
            store = mongoTemplate.findOne(query, StoreInfo.class);
            if(store != null){
                cacheUtils.hsetWithMyExpireTime(CacheKeyConstants.STORE_INFO,storeCode, store, CacheKeyConstants.COMMON_EXPIRE_TIME);
            }
        }
        return store;
    }

    @Override
    public StoreBaseInfo queryStoreInfo(String storeCode) {
        /**
           StoreBaseInfo storeBaseInfo = null;
           StoreInfo storeInfo = queryStoreByCode(storeCode);
        **/
        return null;
    }

    @Override
    public List<StoreInfo> queryStoresByRegionCode(String regionCode) {
        if(StringUtils.isBlank(regionCode)){
            return Lists.newArrayList();
        }
        String key = String.format(CacheKeyConstants.REGION_STORE_INFOS, regionCode);
        String value = redisClient.get(key);
        if(null != value && !"[]".equals(value)){
            List<StoreInfo> result= GsonUtils.fromJson(value, new TypeToken<List<StoreInfo>>(){
            });
            return result;
        }
        Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.and(StoreAttributes.REGION_CODE).is(regionCode);
        query.addCriteria(criteria);
        List<StoreInfo> storeInfos = mongoTemplate.find(query, StoreInfo.class);
        redisClient.set(key, DJStringUtils.GSON.toJson(storeInfos));
        redisClient.expire(key, CacheKeyConstants.REGION_STORE_INFOS_EXPIRE_TIME);
        return storeInfos;
    }

    @Override
    public List<RegionDto> queryAllRegions() {
        String value = redisClient.get(CacheKeyConstants.REGION_ALL);
        List<RegionDto> result =  Lists.newArrayList();  
        if(null != value){
            result= GsonUtils.fromJson(value, new TypeToken<List<RegionDto>>(){
            });
            return result;
        }

       String group = "{$group:{_id:{'regionCode':'$regionCode',regionName:'$regionName'},docsNum:{$sum:1}}}";
       DBObject groupDB= (DBObject)JSON.parse(group);
       AggregationOutput output= mongoTemplate.getCollection("StoreInfo").aggregate(groupDB);
       for(Iterator<DBObject> it = output.results().iterator(); it.hasNext();){
           BasicDBObject dbo = ( BasicDBObject ) it.next();
           BasicDBObject keyValus = (BasicDBObject)dbo.get("_id");
           String regionCode = keyValus.getString("regionCode");
           String regionName = keyValus.getString("regionName");
           if(StringUtils.isNotBlank(regionName) && StringUtils.isNotBlank(regionName)){
               RegionDto regionDto = new RegionDto();
               regionDto.setRegionCode(regionCode);
               regionDto.setRegionName(regionName);
               result.add(regionDto);
           }
       }
       redisClient.set(CacheKeyConstants.REGION_ALL, DJStringUtils.GSON.toJson(result));
       redisClient.expire(CacheKeyConstants.REGION_ALL, CacheKeyConstants.REGION_ALL_EXPIRE_TIME);
       return result;
    }

    @Override
    public List<BranchInfo> queryBranchByRegionCode(String regionCode) {
        String value = redisClient.get(CacheKeyConstants.BRANCH_BY_REGION);
        List<BranchInfo> result =  Lists.newArrayList();  
        if(null != value){
            result= GsonUtils.fromJson(value, new TypeToken<List<BranchInfo>>(){
            });
            return result;
        }

       String group = "[{$match:{regionCode:'"+regionCode+"'}},{$group:{_id:{'branchCode':'$branchCode','saleBranchCode':'$saleBranchCode','branchName':'$branchName'}}}";
       DBObject groupDB= (DBObject)JSON.parse(group);
       AggregationOutput output= mongoTemplate.getCollection("StoreInfo").aggregate(groupDB);
       for(Iterator<DBObject> it = output.results().iterator(); it.hasNext();){
           BasicDBObject dbo = ( BasicDBObject ) it.next();
           BasicDBObject keyValus = (BasicDBObject)dbo.get("_id");
           String branchCode = keyValus.getString("branchCode");
           String branchName = keyValus.getString("branchName");
           String saleBranchCode = keyValus.getString("saleBranchCode");
           if(StringUtils.isNotBlank(branchCode) && StringUtils.isNotBlank(branchName)){
               BranchInfo branch = new BranchInfo();
               branch.setBranchCode(branchCode);
               branch.setSaleBranchCode(saleBranchCode);
               branch.setBranchName(branchName);
               result.add(branch);
           }
       }
       redisClient.set(CacheKeyConstants.BRANCH_BY_REGION, DJStringUtils.GSON.toJson(result));
       redisClient.expire(CacheKeyConstants.BRANCH_BY_REGION, CacheKeyConstants.REGION_ALL_EXPIRE_TIME);
       return result;
    }

    @Override
    public List<StoreInfo> queryStoresByBranchCode(String branchCode, Integer type) {
        String key = CacheKeyConstants.STORE_BY_BRANCH+branchCode+type;
        String value = redisClient.get(key);
        List<StoreInfo> result =  Lists.newArrayList();  
        if(null != value){
            result= GsonUtils.fromJson(value, new TypeToken<List<StoreInfo>>(){
            });
            return result;
        }
        Query query = new Query();
        Criteria criteria = new Criteria();
        if(type == StoreInfo.ORG_TYPE.HR_TYPE){
            criteria.and(StoreAttributes.BRANCH_CODE).is(branchCode);
        }else{
            criteria.and(StoreAttributes.BRANCH_SALE_CODE).is(branchCode);
        }
        query.addCriteria(criteria);
        result = mongoTemplate.find(query, StoreInfo.class);
        redisClient.set(key, DJStringUtils.GSON.toJson(result));
        redisClient.expire(key, CacheKeyConstants.REGION_ALL_EXPIRE_TIME);
        return result;
    }

    @Override
    public List<StoreInfo> queryStoreByStoreType(String storeTypeCode, String regionCode, String saleBranchCode,String storeCode,boolean equalType) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        if(StringUtils.isNotBlank(storeTypeCode) && equalType){
            criteria.and(StoreInfo.StoreAttributes.STORE_TYPE_CODE).is(storeTypeCode);
        }else if(StringUtils.isNotBlank(storeTypeCode) && !equalType){
            criteria.and(StoreInfo.StoreAttributes.STORE_TYPE_CODE).ne(storeTypeCode);
        }
        if(StringUtils.isNotBlank(saleBranchCode)){
            criteria.and(StoreInfo.StoreAttributes.BRANCH_SALE_CODE).is(saleBranchCode);
        }else if(StringUtils.isNotBlank(storeCode)){
            criteria.and(StoreInfo.StoreAttributes.STORE_CODE).is(storeCode);
        } else if (StringUtils.isNotBlank(regionCode)) {
            criteria.and(StoreInfo.StoreAttributes.REGION_CODE).is(regionCode);
        }
        query.addCriteria(criteria);
        return mongoTemplate.find(query, StoreInfo.class);
    }

    @Override
    public List<StoreInfo> queryStoreByStoreCodes(List<String> storeCodes) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.and(StoreInfo.StoreAttributes.STORE_CODE).in(storeCodes);
        query.addCriteria(criteria);
        return mongoTemplate.find(query, StoreInfo.class);
    }

    /**
     * 查询所有店铺数据
     */
    @Override
    public List<StoreInfo> queryAllStore() {
        // 执行查询
        return mongoTemplate.findAll(StoreInfo.class);
    }

    
    /**
     * 根据销售大区编码查询门店信息
     */
    @Override
    public StoreInfo queryBranchCodeBySaleCode(String branchCode) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.and(StoreInfo.StoreAttributes.BRANCH_SALE_CODE).in(branchCode);
        query.addCriteria(criteria);
        return mongoTemplate.findOne(query, StoreInfo.class);
    }
    
    @Override
    public StaffInfo queryStaffInfoByStaffId(String staffId) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("staffId", staffId);
        StaffInfo result;
        try {
            result = dalClient.queryForObject("STAFFINFO.QUERY_STAFFINFO_BYSTAFFID", paramMap, StaffInfo.class) ;
        } catch (Exception e) {
            LOGGER.error("queryStaffInfoByStaffId error ", e);
            return null;
        }
        return result;
    }

    @Override
    public boolean updatePositionInfo(String roleType,String orgId,String positionName, String positionId, String staffid) {
        boolean result = false;
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("staffId", staffid);
        paramMap.put("lastPositionName", positionName);
        paramMap.put("lastPositionId", positionId);
        paramMap.put("orgId", orgId);
        paramMap.put("roleType", roleType);
        try {
           int daoResult =  dalClient.execute("STAFFINFO.UPSERT_STAFF_INFO", paramMap);
           LOGGER.info("updatePositionInfo positionName:{}, positionId:{},  staffid:{} ,daoResult:{}",positionName,positionId,staffid,daoResult);
           if(daoResult > 0){
               result = true ;
           }
        } catch (Exception e) {
            LOGGER.error("updatePositionInfo error ", e);
        }
        return result;
    }
}
